package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**\
 * 自定义切片类  公共字段自动填充
 */
@Aspect  // 表示当前类是一个切面类
@Component // 将其注入到Spring容器中
@Slf4j
public class AutoFillAspect {

    @Before("@annotation(com.sky.annotation.AutoFill)")  // 前置通知，在目标方法执行前执行
    public void autoFIll(JoinPoint joinPoint){
        log.info("开始进行公共字段的自动填充");

        // 1 获取到目标方法上的注解 ，并拿到注解中的属性值
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();  // 获取到目标方法签名对象 强制转换成MethodSignature对象
//        methodSignature.getDeclaringType()  // 获取到目标方法所在的类
        Method method = methodSignature.getMethod();  // 获取到目标方法 对象
        AutoFill annotation = method.getAnnotation(AutoFill.class); // 获取到目标方法上的注解
        OperationType operationType = annotation.value();  // 获取到注解中的属性值



        //获取到目标方法的参数对象
        Object[] args = joinPoint.getArgs();  //获取目标方法的参数数组 也就是那个封装了请求参数的实体类
        if(args == null || args.length ==0){  // 如果没有参数，直接返回
            return;
        }
        //如果有参数就拿到当前的参数对象
        Object entity = args[0];  // 获取到目标方法的参数对象


        //3 判断注解上的属性值，然后进行对应的赋值操作
        try {
            if(operationType == OperationType.INSERT){  // 如果是插入操作，就行 创建时间 更新时间 创建人 修改人
                Method setCreateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setCreateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                setCreateTime.invoke(entity, LocalDateTime.now());
                setUpdateTime.invoke(entity, LocalDateTime.now());
                setCreateUser.invoke(entity, BaseContext.getCurrentId());
                setUpdateUser.invoke(entity, BaseContext.getCurrentId());


            } else if (operationType == OperationType.UPDATE) { // 如果是更新操作，就更新更新时间 和 更新人
                Method setUpdateTime = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                Method setUpdateUser = entity.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                setUpdateTime.invoke(entity, LocalDateTime.now());
                setUpdateUser.invoke(entity, BaseContext.getCurrentId());


            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

    }
}
